gusucode.com > VC 图像数字识别系统+开发文档-源码程序 > VC 图像数字识别系统+开发文档-源码程序/code/一个vc写的数字识别程序/一个VC写的数字识别程序/数字识别系统源代码/ChildView.cpp
//Download by http://www.NewXing.com // ChildView.cpp : implementation of the CChildView class // #include "stdafx.h" #include "DigitRec.h" #include "ChildView.h" #include "INPUT1.h" #include "mydiblib.h" #include "Bp.h" #include "DBpParamater.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif void ThiningDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight); ///////////////////////////////////////////////////////////////////////////// // CChildView CChildView::CChildView() { fileloaded=false; gyhinfoinput=false; gyhfinished=false; m_hDIB=NULL; } CChildView::~CChildView() { } BEGIN_MESSAGE_MAP(CChildView,CWnd ) //{{AFX_MSG_MAP(CChildView) ON_WM_PAINT() ON_COMMAND(IDmy_FILE_OPEN_BMP, OnFileOpenBmp) ON_COMMAND(IDmy_FILE_SAVE_BMP, OnFileSaveBmp) ON_COMMAND(IDmy_IMGPRC_SHRINK_ALIGN, OnImgprcShrinkAlign) ON_COMMAND(IDmy_IMGPRC_ALL, OnImgprcAll) ON_COMMAND(IDmy_IMGPRC_256ToGray, OnIMGPRC256ToGray) ON_COMMAND(IDmy_IMGPRC_DIVIDE, OnImgprcDivide) ON_COMMAND(IDmy_IMGPRC_TO_DIB_AND_SAVE, OnImgprcToDibAndSave) ON_COMMAND(IDmy_IMGPRC_REMOVE_NOISE, OnImgprcRemoveNoise) ON_COMMAND(IDmy_IMGPRC_STANDARIZE, OnImgprcStandarize) ON_COMMAND(IDmy_IMGPRC_THINNING, OnImgprcThinning) ON_COMMAND(IDmy_IMGPRC_ADJUST_SLOPE, OnImgprcAdjustSlope) ON_COMMAND(IDmy_IMGPRC_GrayToWhiteBlack, OnIMGPRCGrayToWhiteBlack) ON_COMMAND(IDmy_IMGPRC_SHARP, OnImgprcSharp) ON_COMMAND(IDmy_FILE_RE_LOAD_BMP, OnFileReLoadBmp) ON_COMMAND(ID_INPUT1, OnInputGuiyihuaInfo) ON_COMMAND(IDmy_BPNET_TRAIN, OnBpnetTrain) ON_COMMAND(IDmy_BPNET_RECOGNIZE, OnBpnetRecognize) ON_COMMAND(ID_aver, Onaver) ON_COMMAND(ID_Gass, OnGass) ON_COMMAND(ID_Mid, OnMid) ON_COMMAND(IDmy_IMGPRC_EQUALIZE, OnImgprcEqualize) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChildView message handlers BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) return FALSE; cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); return TRUE; } void CChildView::OnPaint() { CPaintDC dc(this); // device context for painting OnDraw(&dc); // Do not call CWnd::OnPaint() for painting messages } //打开256色位图文件 void CChildView::OnFileOpenBmp() { //创建一个打开文件对话框,并返回完整的文件路径 static char BASED_CODE szFilter[] = "256色位图文件(*.bmp)|"; CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL); if(dlg.DoModal() == IDOK) strPathName = dlg.GetPathName(); else return; //创建一个文件对象 CFile file; //以只读模式打开文件 file.Open (strPathName,CFile::modeRead); //读取文件到HDIB句柄中. 注意:此时只是读取位图文件中文件头之后的部分,不含文件头 m_hDIB=::ReadDIBFile (file); //HDIB句柄: 就是一块存储位图数据的内存区域的地址 //HDIB句柄包含:位图信息头、调色板(如果有的话)、DIB图像数据 //关闭文件 file.Close (); //指向DIB的指针(指向位图信息头) BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)m_hDIB); // 获取DIB中颜色表中的颜色数目 WORD wNumColors; wNumColors = ::DIBNumColors((char*)lpDIB); // 判断是否是256色位图 if (wNumColors != 256) { // 提示用户 MessageBox("非256色位图!", "系统提示" , MB_ICONINFORMATION | MB_OK); // 解除锁定 ::GlobalUnlock((HGLOBAL)m_hDIB); // 返回 return; } //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); //更改位图文件是否已加载的标志 fileloaded=true; //gyhinfoinput=false; //2004.4.26修改 gyhfinished=false; } //取消一切更改,重新加载位图文件 void CChildView::OnFileReLoadBmp() { //判断位图文件是否已加载。如果尚未加载,则弹出文件打开对话框 if(fileloaded==false) { OnFileOpenBmp(); if(fileloaded==false) return; } //创建一个文件对象 CFile file; //以只读模式打开文件 file.Open (strPathName,CFile::modeReadWrite); m_hDIB=::ReadDIBFile (file); //关闭文件 file.Close (); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnFileSaveBmp() { //创建一个保存文件对话框,并返回完整的文件路径 static char BASED_CODE szFilter[] = "256色位图文件(*.bmp)|"; CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL); if(dlg.DoModal() == IDOK) strPathNameSave = dlg.GetPathName(); else return; //在文件名后添加.bmp后缀 //strPathNameSave+=".bmp"; //以读写模式打开一个文件。如果文件不存在,则创建之 CFile file(strPathNameSave, CFile::modeReadWrite|CFile::modeCreate); ::SaveDIB (m_hDIB,file); //关闭文件 file.Close (); } //一次性预处理 void CChildView::OnImgprcAll() { if(fileloaded==false) { if(::AfxMessageBox ("请先打开一个图像文件再进行此操作!",MB_YESNO|MB_ICONSTOP)==IDNO) return; } //打开文件 OnFileReLoadBmp(); //判断用户是否已输入归一化高度和宽度信息 if(gyhinfoinput==false) OnInputGuiyihuaInfo(); //将256色图转换为灰度图 OnIMGPRC256ToGray(); //将灰度图二值化 OnIMGPRCGrayToWhiteBlack(); //梯度锐化 //OnImgprcSharp(); //去除离散杂点噪声 OnImgprcRemoveNoise(); //调整数字字符的整体倾斜 OnImgprcAdjustSlope(); //分割并画框标识 OnImgprcDivide(); //将分割后的数字字符宽、高标准化,以便于下一步与BP网络的输入兼容 OnImgprcStandarize(); ConvertGrayToWhiteBlack(m_hDIB); //紧缩重排数字字符 OnImgprcShrinkAlign(); //分别保存这些已经经过分割、标准后的单个的数字字符到bmp文件,以便后续过程使用 //OnImgprcToDibAndSave(); //OnPreprocThin(); } //图像预处理第1步:将256色图像转化为灰度图像 void CChildView::OnIMGPRC256ToGray() { Convert256toGray(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } //图像预处理第2步:将灰度图二值化 void CChildView::OnIMGPRCGrayToWhiteBlack() { ConvertGrayToWhiteBlack(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } //图像预处理第3步:梯度锐化 void CChildView::OnImgprcSharp() { GradientSharp(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } //图像预处理第4步:去离散杂点噪声 void CChildView::OnImgprcRemoveNoise() { RemoveScatterNoise(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } //图像预处理第5步:倾斜度调整 void CChildView::OnImgprcAdjustSlope() { SlopeAdjust(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } //图像预处理第6步:分割,并在分割出来的字符外面画框以标识 void CChildView::OnImgprcDivide() { m_charRect=CharSegment(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); DrawFrame(pDC,m_hDIB,m_charRect,2,RGB(20,60,200)); } //图像预处理第7步:标准归一化 //将分割出来的各个不同宽、高的数字字符宽、高统一 void CChildView::OnImgprcStandarize() { StdDIBbyRect(m_hDIB,w_sample,h_sample); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); DrawFrame(pDC,m_hDIB,m_charRect,2,RGB(21,255,25)); gyhfinished=true; } //图像预处理第8步:紧缩重排已经分割完毕的数字字符,并形成新的位图句柄 void CChildView::OnImgprcShrinkAlign() { m_hDIB=AutoAlign(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); DrawFrame(pDC,m_hDIB,m_charRect,1,RGB(252,115,27)); } //图像预处理第9步:将最终标准化后的字符图像分为单个单个的HDIB保存,并存为.bmp文件 void CChildView::OnImgprcToDibAndSave() { unsigned char* lpSrc; int w,h; w=m_charRect.front ().Width() ; h=m_charRect.front ().Height() ; m_dibRect.clear (); m_dibRectCopy.clear (); int i_src,j_src; int i,j; int counts=0; CRect rect,rectnew; BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)m_hDIB); BYTE* lpDIBBits=(BYTE*)::FindDIBBits ((char*)lpDIB); BYTE* lpNewDIBBits; BYTE* lpDst; LONG lLineBytes=(digicount*w+3)/4*4; LONG lLineBytesnew =(w+3)/4*4; HDIB hDIB=NULL; while(!m_charRect.empty ()) { hDIB=::NewDIB (w,h,8); lpDIB=(BYTE*) ::GlobalLock((HGLOBAL)hDIB); lpNewDIBBits = (BYTE*)::FindDIBBits((char*)lpDIB); lpDst=(BYTE*)lpNewDIBBits; memset(lpDst,(BYTE)255,lLineBytesnew * h); rect=m_charRect.front (); m_charRect.pop_front (); for(i=0;i<h;i++) for(j=0;j<w;j++) { i_src=rect.top + i; j_src=j+counts*w; lpSrc=(BYTE *)lpDIBBits + lLineBytes * i_src + j_src; lpDst=(BYTE *)lpNewDIBBits + lLineBytesnew * i + j; *lpDst=*lpSrc; } ::GlobalUnlock (hDIB); m_dibRect.push_back (hDIB); counts++; } m_charRect=m_charRectCopy; m_dibRectCopy=m_dibRect; //输出为.bmp文件 CString str; counts=1; while(!m_dibRect.empty ()) { str.Format ("part%d.bmp",counts); //str=strPath+"\\"+str; CFile file(str, CFile::modeReadWrite|CFile::modeCreate); hDIB=m_dibRect.front (); ::SaveDIB (hDIB,file); m_dibRect.pop_front (); file.Close (); counts++; } m_dibRect=m_dibRectCopy; } void CChildView::OnImgprcThinning() { Thinning(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnInputGuiyihuaInfo() { CINPUT1 input; input.w =8; input.h =16; if(input.DoModal ()!=IDOK) return; w_sample=input.w; h_sample=input.h; gyhinfoinput=true; } void CChildView::OnBpnetTrain() { OnImgprcAll(); //判断是否经过了归一划的处理 if(gyhfinished==false) { //如果没有进行提示错误并返回 ::MessageBox(NULL,"没有进行归一划预处理",NULL,MB_ICONSTOP); return; } //建立BP网络训练参数对话框 CDBpParamater BpPa; //初始化变量 BpPa.m_a=0; BpPa.m_eta=0.015; BpPa.m_ex=0.001; BpPa.m_hn=10; // 显示对话框 if(BpPa.DoModal()!=IDOK) { //返回 return; } //用户获得参数信息 //相关系数 double momentum=BpPa.m_a; //最小均方误差 double min_ex=BpPa.m_ex; //隐层数目 int n_hidden=BpPa.m_hn; //训练步长 double eta=BpPa.m_eta; //获得指向DIB的指针 BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) m_hDIB); //获得指向DIB象素的指针,并指向象素的起始位置 BYTE *lpDIBBits =(BYTE*)::FindDIBBits((char *)lpDIB); //获得颜色信息 int numColors=(int) ::DIBNumColors((char *)lpDIB); //不是灰度图返回 if (numColors!=256) { ::GlobalUnlock((HGLOBAL) m_hDIB); ::MessageBox(NULL,"只能处理灰度图像",NULL,MB_ICONSTOP); return; } //获取图像的宽度 LONG lWidth = (LONG) ::DIBWidth((char *)lpDIB); //获取图像的高度 LONG lHeight = (LONG) ::DIBHeight((char *)lpDIB); //计算图像每行的字节数 LONG lLineByte = (lWidth+3)/4*4; //归一化的宽度 LONG lSwidth = w_sample; //归一化的高度 LONG LSheight = h_sample; //指向输入样本的特征向量的指针 double **data_in; //从输入的训练样本中提取特征向量 data_in = code ( lpDIBBits, digicount, lLineByte, lSwidth, LSheight); //计算输入层结点的数目 int n_in = LSheight*lSwidth; double out[][4]={ 0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.9, 0.1,0.1,0.9,0.1, 0.1,0.1,0.9,0.9, 0.1,0.9,0.1,0.1, 0.1,0.9,0.1,0.9, 0.1,0.9,0.9,0.1, 0.1,0.9,0.9,0.9, 0.9,0.1,0.1,0.1, 0.9,0.1,0.1,0.9}; double **data_out; data_out = alloc_2d_dbl(digicount,4); for(int i=0;i<digicount;i++) { for(int j=0;j<4;j++) data_out[i][j]=out[i%10][j]; } BpTrain( data_in, data_out, n_in,n_hidden,min_ex,momentum,eta,digicount); ::GlobalUnlock(m_hDIB); CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnBpnetRecognize() { // TODO: Add your command handler code here OnImgprcAll(); //判断是否经过了归一划的处理 if(gyhfinished==false) { //如果没有进行提示错误并返回 ::MessageBox(NULL,"没有进行归一划预处理",NULL,MB_ICONSTOP); return; } //获得指向DIB的指针 BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) m_hDIB); //获得指向DIB象素的指针,并指向象素的起始位置 BYTE *lpDIBBits =(BYTE*)::FindDIBBits((char *)lpDIB); //获得颜色信息 int numColors=(int) ::DIBNumColors((char *)lpDIB); //不是灰度图返回 if (numColors!=256) { ::GlobalUnlock((HGLOBAL) m_hDIB); ::MessageBox(NULL,"只能处理256色图像",NULL,MB_ICONSTOP); return; } //获取图像的宽度 LONG lWidth = (LONG) ::DIBWidth((char *)lpDIB); //获取图像的高度 LONG lHeight = (LONG) ::DIBHeight((char *)lpDIB); //计算图像每行的字节数 LONG lLineByte = (lWidth+3)/4*4; //归一化的宽度 LONG lSwidth = w_sample; //归一化的高度 LONG LSheight = h_sample; // 读取结点信息 int n[3]; if(r_num(n,"num")==false) return; //获得输入层结点数目 int n_in=n[0]; //获得隐层结点数目 int n_hidden=n[1]; //获得输出层结点数目 int n_out=n[2]; //判断待识别样本的归一划信息是否与训练时相同 if(n_in!=lSwidth*LSheight) { //如果不相同提示错误并返回 ::MessageBox(NULL,"归一划尺寸与上一次训练时不一致",NULL,MB_ICONSTOP); return; } //指向输入样本的特征向量的指针 double **data_in; //从输入的训练样本中提取特征向量 data_in = code ( lpDIBBits, digicount, lLineByte, lSwidth, LSheight); //根据提取的特征进行样本识别 CodeRecognize(data_in, digicount,n_in,n_hidden,n_out); ::GlobalUnlock(m_hDIB); CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnDraw(CDC *pDC) { if(m_hDIB!=NULL) DisplayDIB(pDC,m_hDIB); } void CChildView::Onaver() { // TODO: Add your command handler code here //设定模板参数 double tem[9]={1,1,1, 1,1,1, 1,1,1}; //设定模板系数 double xishu = 0.111111; //进行模板操作 m_hDIB =Template(m_hDIB,tem ,3,3, xishu); //显示图像 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnGass() { // TODO: Add your command handler code here //设定模板参数 double tem[9]={1,2,1, 2,4,2, 1,2,1}; //设定模板系数 double xishu = 0.0625; //进行模板操作 m_hDIB =Template(m_hDIB,tem ,3,3, xishu); //显示图像 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnMid() { // TODO: Add your command handler code here //进行中值滤波 m_hDIB =MidFilter(m_hDIB,3,3); //显示图像 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); } void CChildView::OnImgprcEqualize() { Equalize(m_hDIB); //显示图像 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); }